//全局安装ts 让电脑有ts运行环境  npm install -g typescript / cnpm install -g typescript
// tsc -v 查看ts 是否安装成功
// typescript   给 js 变量设置类型定义, 然后将js 弱类型语言 变成 强类型语言
// es 模块化语法   vue react
// 导入 import / import {} 导出 export / export default
//commonjs  主要用在 nodejs   vue react
// moudule.exports = {}  导入 require(路径)

// ts 包含js , 任何js 语法都可以在ts 中使用

// let a: number = 100
// console.log(a);

// void类型
// const fun = (): void => {

// }

// function fn1(): void {

// }

// unknown 类型 表示未知的数据类型
// let b: unknown = {}

// 数组类型
// 泛型声明数组的方式
// let arr: Array<string | number> = [1, '2', 'c']
// 字面量声明方式
// let arr: (string | number)[] = ['1', '2', 100]

// 元祖类型
// let arr: [string, number, Array<any>] = ['1', 100, []];

// 枚举类型
// enum Sex {
//     male = '男',
//     female = '女',
//     unknown = '未知'
// }

// console.log('Sex', Sex);
// let girl: Sex = Sex.female
// console.log(girl);


// symbol 类型: 特点: 不可变且唯一的
// let sym1 = Symbol()
// let sym2 = Symbol()
// console.log(sym1 === sym2);

// let obj = {
//     [sym1]: '张三'
// }

// console.log(obj[sym1]);

// ts 中的函数
//? 可选参数
// ...arr 剩余参数
// const f1 = (m: string, n: number, ...arr: Array<any>): string => {
//     console.log(m);
//     console.log(n);
//     console.log(arr);
//     return m
// }

// f1('10', 1, '张三', '李四')

// interface
//可以创建一个数据类型 去自定义数据类型
// 特点: 一般用来创建对象类型

// interface person {
//     name: string,
//     age: number,
//     say(m: string, n: number): string
// }

// let p: person = {
//     name: '小月月',
//     age: 20,
//     say() {
//         return this.name
//     }
// }


// type
// 可以使用type 自定义任意类型

// type str = string
// type arr = Array<any>
// type person = {
//     name: string,
//     age: number,
//     say(m: string, n: number): string
// }
// // let a: str = 100
// let p: person = {
//     name: '小月月',
//     age: 20,
//     say() {
//         return this.name
//     }
// }


// 接口的属性

// interface person {
//     name?: string, // 可选属性
//     readonly age: number, // 只读属性
//     say(m: string, n: number): string
// }

// let p: person = {
//     age: 10,
//     say() {
//         return ''
//     }
// }

// p.age = 20


// 接口的继承
// interface Animal {
//     name: string,
//     age: number,
//     // eat(): string
//     eat: () => string
// }

// interface cat extends Animal {
//     killmouse: string,
//     run(): string
// }

// let xiaohua: cat = {
//     name: '小花',
//     age: 5,
//     eat() {
//         return '鱼'
//     },
//     killmouse: '抓老鼠',
//     run() {
//         return '跑'
//     }
// }


// 使用接口定义额外属性/ 可扩展属性
// interface res {
//     id: number,
//     data: Array<{ id: string }>,
//     [key: string]: any
// }

// let r: res = {
//     id: 200,
//     data: [{ id: '1' }, { id: '2' }, { id: '3' }],
//     status: 'success',
//     img: 'url'
// }


// 类型断言
// 在使用一个数据的时候. ts 语法提示该数据没有某一个属性类型, 此时可以给该数据类型断言
let student = {}

interface stu {
    name: string,
    age: number
}
(student as stu).name = '张三'

// 类型断言
// 当一个类型可能为null |Element  或者是  string|undefined
// 当处理数据类型为非null 或非 undefiend时候, 可以使用 数据!
// 这种语法.告诉程序该数据为非null 或非undefined
// let box = document.querySelector('#box')!
// box.innerHTML = '123'



// 泛型

function fn1(m: string): string {
    return m
}

function fn2(n: number): number {
    return n
}

// function fn3(k: string | number): string | number {
//     return k
// }

// function fn4<T>(k: T): T {
//     return k
// }
// fn4(10)
// fn4('10')

// 泛型在接口interface 中的使用
// interface Fn {
//     (m: string): string
// }

// let f: Fn = (m) => {
//     return m
// }

// f('100')
// f(true)


//使用泛型 改造代码
interface Fn<T> {
    (m: T): T
}

let f2: Fn<string> = (m) => {
    return m
}
// f2(null)

// 泛型在类中的使用
// 给泛型设置约束
type scopeType = string | number | boolean;
class Obj<T extends scopeType>{
    nameArr: T[] = [];
    push(name: T) {
        this.nameArr.push(name)
    }
}

let obj1 = new Obj()

obj1.push('张三')
obj1.push('李四')
obj1.push('王五')
obj1.push(true)
// obj1.push({})
console.log(obj1);



